package cheme.ProcessEditor.Parts.Streams.Tag;

import java.util.List;

import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gef.requests.CreateRequest;
import org.eclipse.gef.requests.GroupRequest;

import cheme.ProcessEditor.Policies.ToolbarLayoutEditPolicy;
import cheme.ProcessModel.IChild;
import cheme.ProcessModel.IParent;
import cheme.ProcessModel.Cmds.AddCmd;
import cheme.ProcessModel.Cmds.MoveCmd;
import cheme.ProcessModel.Cmds.OrphanChildCmd;
import cheme.ProcessModel.ProcessUnits.Streams.Tags.ITagComponent;
import cheme.ProcessModel.ProcessUnits.Streams.Tags.Tag;
import cheme.ProcessModel.ProcessUnits.Streams.Tags.TagComponent;
import cheme.ProcessModel.ProcessUnits.Streams.Tags.TagComponentList;

/*
 * Like most layout policies, this is where moveing visual elements around a 
 * container is handled, specifically, stream descriptors into/out of/up or down
 * a stream tag.
 */
public class PolicyTagLayout extends ToolbarLayoutEditPolicy
{
	@Override
	protected Command getCloneCommand(ChangeBoundsRequest request)
	{
		if(REQ_ORPHAN_CHILDREN.equals(request.getType()))
		{
			return getOrphanChildrenCommand((GroupRequest)request);
		}
		
		return super.getCloneCommand(request);
	}
	
	@Override
	protected void showLayoutTargetFeedback(Request request)
	{
		/*
		 * Override to dissallow any show of feedback--drops aren't allowed here.
		 */
		
		boolean allowShow = false;
		
		if(REQ_CREATE.equals(request.getType()))
		{
			if((((CreateRequest)request).getNewObject() instanceof TagComponent))
			{
				allowShow = true;
			}
		}
		else if(REQ_ADD.equals(request.getType()))
		{
			List<GraphicalEditPart> parts = ((ChangeBoundsRequest)request).getEditParts();
			
			if(parts.size() > 0)
			{
				/*
				 * All model elements have to be of TagComponent type
				 */
				
				allowShow = true;
				
				for(GraphicalEditPart part : parts)
				{
					allowShow &= (part.getModel() instanceof TagComponent);
				}			
			}
		}
		
		if(allowShow)
		{
			super.showLayoutTargetFeedback(request);
		}
	}
	
	protected int getFeedbackIndexFor(Request request)
	{
		return -1;
	}

	@Override
	protected Command createMoveChildCommand(EditPart child, EditPart after)
	{
		return null;
	}
	
	protected Command getOrphanChildrenCommand(GroupRequest request)
	{
		List<EditPart> editParts = request.getEditParts();
		CompoundCommand cmd= new CompoundCommand();
		
		for (int i = 0; i < editParts.size(); i++)
		{
			OrphanChildCmd orphan = new OrphanChildCmd((IChild)editParts.get(i).getModel());
			cmd.add(orphan);
		}
		
		return cmd.unwrap();
	}

	@Override
	protected Command getCreateCommand(CreateRequest request)
	{
		CompoundCommand cmd = new CompoundCommand();
		
		/*
		 * Potenitially chain a command to create the initial list.
		 */
		
		Tag tag = (Tag)getHost().getModel();
		TagComponentList parent = tag.getTagComponentList(); 
		
//		if(null == parent)
//		{
//			parent = new TagComponentList(tag);
//			cmd.add(new AddCmd(parent, ((Tag)getHost().getModel()), Tag.LIST_INDEX));
//		}
		
		cmd.add(new AddCmd(new TagComponent(parent), parent));
				
		return cmd.unwrap();
		
//		return null;
	}
	
	@Override
	protected Command createAddCommand(EditPart child, EditPart after)
	{		
		/*
		 * need to take into account that the afterChild could be null and will need to add the child to the end.
		 */
		Command cmd = null;

		IChild moveChild = (IChild)child.getModel();
		
		if(moveChild instanceof ITagComponent)
		{
			CompoundCommand compund = new CompoundCommand();
			Tag tag = (Tag)getHost().getModel();
			IParent originalList = moveChild.getParent();
			IParent newList = tag.getTagComponentList();
			
			compund.add(new MoveCmd(moveChild, originalList, newList, -1));
			
			cmd = compund.unwrap();
		}
		
		return cmd;
	}
}